package com.xnyzc.lhy.order.service.impl.comment;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xnyzc.lhy.common.component.redis.RedisCommon;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.client.EClientUserType;
import com.xnyzc.lhy.common.penum.comment.ECommentGradeType;
import com.xnyzc.lhy.common.penum.comment.EEvaluationIsShow;
import com.xnyzc.lhy.common.penum.comment.EOrderIsComment;
import com.xnyzc.lhy.common.penum.driver.EServiceFraction;
import com.xnyzc.lhy.common.penum.order.EOrderNoType;
import com.xnyzc.lhy.common.penum.star.EStarType;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.order.entity.comment.OaSysComment;
import com.xnyzc.lhy.order.entity.order.OaCOrderApprovalOfficial;
import com.xnyzc.lhy.order.entity.order.OaCOrderDeptOfficial;
import com.xnyzc.lhy.order.entity.order.OaCOrderPersonal;
import com.xnyzc.lhy.order.entity.order.OaCOrderPersonalOfficial;
import com.xnyzc.lhy.order.entity.order.OaDOrder;
import com.xnyzc.lhy.order.entity.order.OaOrderEvaluation;
import com.xnyzc.lhy.order.entity.user.OaDUserInfo;
import com.xnyzc.lhy.order.mapper.comment.OaSysCommentMapper;
import com.xnyzc.lhy.order.mapper.order.OaCOrderApprovalOfficialMapper;
import com.xnyzc.lhy.order.mapper.order.OaCOrderDeptOfficialMapper;
import com.xnyzc.lhy.order.mapper.order.OaCOrderPersonalMapper;
import com.xnyzc.lhy.order.mapper.order.OaCOrderPersonalOfficialMapper;
import com.xnyzc.lhy.order.mapper.order.OaDOrderMapper;
import com.xnyzc.lhy.order.mapper.order.OaOrderEvaluationMapper;
import com.xnyzc.lhy.order.mapper.user.OaDUserInfoMapper;
import com.xnyzc.lhy.order.mapper.work.OaDWorkStatisticsMapper;
import com.xnyzc.lhy.order.service.comment.IOaSysCommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 评价配置表 服务实现类
 * </p>
 *
 * @author zhuyubin
 * @since 2019-08-05
 */
@Service
public class OaSysCommentServiceImpl extends ServiceImpl<OaSysCommentMapper, OaSysComment> implements IOaSysCommentService {

    private static final Integer INIT_TOTAL_SERVICE_SCORE = EServiceFraction.serviceFraction.getValue();

    @Autowired
    private OaSysCommentMapper oaSysCommentMapper;
    @Autowired
    private OaOrderEvaluationMapper oaOrderEvaluationMapper;
    @Autowired
    private OaCOrderPersonalMapper oaCOrderPersonalMapper;
    @Autowired
    private OaCOrderPersonalOfficialMapper oaCOrderPersonalOfficialMapper;
    @Autowired
    private OaCOrderDeptOfficialMapper oaCOrderDeptOfficialMapper;
    @Autowired
    private OaCOrderApprovalOfficialMapper oaCOrderApprovalOfficialMapper;
    @Autowired
    private RedisCommon redisCommon;
    @Autowired
    private OaDWorkStatisticsMapper oaDWorkStatisticsMapper;
    @Autowired
    private OaDOrderMapper oaDOrderMapper;
    @Autowired
    private OaDUserInfoMapper oaDUserInfoMapper;

    /**
     * 获取司机的全部评价配置信息
     * @param userType 用户类型
     * @param tag 租户
     * @return
     */
    @Override
    public List<Map<String, Object>> getComment(String userType, String tag){
        List<Map<String, Object>> result = new ArrayList<>();
        List<OaSysComment> oaSysCommentsAll = oaSysCommentMapper.selectList(
                Wrappers.<OaSysComment>lambdaQuery()
                        .eq(OaSysComment::getUserType, userType)
                        .eq(OaSysComment::getTag, tag)
                        .groupBy(OaSysComment::getCommentType)
        );
        if (CheckUtil.objIsEmpty(oaSysCommentsAll)){
            return result;
        }
        for (int i = 0; i < oaSysCommentsAll.size(); i++) {
            Map<String, Object> map = new HashMap<>(16);
            List<OaSysComment> oaSysComments = oaSysCommentMapper.selectList(
                    Wrappers.<OaSysComment>lambdaQuery()
                            .eq(OaSysComment::getCommentType, i)
                            .eq(OaSysComment::getUserType, userType)
                            .eq(OaSysComment::getTag, tag)
                            .orderByAsc(OaSysComment::getSort)
            );
            List<Map<String, Object>> comments = new ArrayList<>();
            for (OaSysComment oaSysComment : oaSysComments) {
                Map<String, Object> comment = new HashMap<>(16);
                comment.put("evaluateId", oaSysComment.getCommentId().toString());
                comment.put("evaluateName", oaSysComment.getCommentContent());
                comments.add(comment);
            }
            map.put("starEvaluate", comments);
            map.put("starName", EStarType.findById(i).getValue());
            result.add(map);
        }
        return result;
    }

    /**
     * 评价
     * @param userId 用户id
     * @param userType 用户类型
     * @param tag 租户
     * @param orderNo 订单号
     * @param comments 评价数组
     * @return
     */
    @Override
    public String evaluation(Long userId, Integer userType, String tag, String orderNo, List<Long> comments){
        Date date = new Date();
        // 自费叫车
        if (orderNo.contains(EOrderNoType.ZFJC.getType())){
            OaCOrderPersonal oaCOrderPersonal = oaCOrderPersonalMapper.selectOne(this.getQw(userId, userType, tag, orderNo));
            if (CheckUtil.objIsEmpty(oaCOrderPersonal)){
                throw PangException.create(EErrorCode.unOrder);
            }
            if (EClientUserType.c.getValue().equals(userType)){
                if (EOrderIsComment.yes.getValue().equals(oaCOrderPersonal.getIsComment())){
                    throw PangException.create(EErrorCode.isCarpool);
                }
            } else {
                if (this.isOaDOrderComment(orderNo)){
                    throw PangException.create(EErrorCode.isCarpool);
                }
            }
            this.insertOrderEvaluation(orderNo, userId, oaCOrderPersonal.getDriverId(), userType, comments, tag, date);
            return this.getZFJC(oaCOrderPersonal, userId, userType, date);
        }
        // 个人公务
        else if (orderNo.contains(EOrderNoType.GRGW.getType())){
            OaCOrderPersonalOfficial oaCOrderPersonalOfficial = oaCOrderPersonalOfficialMapper.selectOne(this.getQw(userId, userType, tag, orderNo));
            if (CheckUtil.objIsEmpty(oaCOrderPersonalOfficial)){
                throw PangException.create(EErrorCode.unOrder);
            }
            if (EClientUserType.c.getValue().equals(userType)){
                if (EOrderIsComment.yes.getValue().equals(oaCOrderPersonalOfficial.getIsComment())){
                    throw PangException.create(EErrorCode.isCarpool);
                }
            } else {
                if (this.isOaDOrderComment(orderNo)){
                    throw PangException.create(EErrorCode.isCarpool);
                }
            }
            this.insertOrderEvaluation(orderNo, userId, oaCOrderPersonalOfficial.getDriverId(), userType, comments, tag, date);
            return this.getGRGW(oaCOrderPersonalOfficial, userId, userType, date);
        }
        // 部门公务
        else if (orderNo.contains(EOrderNoType.BMGW.getType())){
            OaCOrderDeptOfficial oaCOrderDeptOfficial = oaCOrderDeptOfficialMapper.selectOne(this.getQw(userId, userType, tag, orderNo));
            if (CheckUtil.objIsEmpty(oaCOrderDeptOfficial)){
                throw PangException.create(EErrorCode.unOrder);
            }
            if (EClientUserType.c.getValue().equals(userType)){
                if (EOrderIsComment.yes.getValue().equals(oaCOrderDeptOfficial.getIsComment())){
                    throw PangException.create(EErrorCode.isCarpool);
                }
            } else {
                if (this.isOaDOrderComment(orderNo)){
                    throw PangException.create(EErrorCode.isCarpool);
                }
            }
            this.insertOrderEvaluation(orderNo, userId, oaCOrderDeptOfficial.getDriverId(), userType, comments, tag, date);
            return this.getBMGW(oaCOrderDeptOfficial, userId, userType, date);
        }
        // 审批公务
        else if (orderNo.contains(EOrderNoType.SPGW.getType())){
            OaCOrderApprovalOfficial oaCOrderApprovalOfficial = oaCOrderApprovalOfficialMapper.selectOne(this.getQw(userId, userType, tag, orderNo));
            if (CheckUtil.objIsEmpty(oaCOrderApprovalOfficial)){
                throw PangException.create(EErrorCode.unOrder);
            }
            if (EClientUserType.c.getValue().equals(userType)){
                if (EOrderIsComment.yes.getValue().equals(oaCOrderApprovalOfficial.getIsComment())){
                    throw PangException.create(EErrorCode.isCarpool);
                }
            } else {
                if (this.isOaDOrderComment(orderNo)){
                    throw PangException.create(EErrorCode.isCarpool);
                }
            }
            this.insertOrderEvaluation(orderNo, userId, oaCOrderApprovalOfficial.getDriverId(), userType, comments, tag, date);
            return this.getSPGW(oaCOrderApprovalOfficial, userId, userType, date);
        }
        // 非法订单号
        else {
            throw PangException.create(EErrorCode.unOrderNo);
        }
    }

    /**
     * 插入订单评价
     * @param orderNo 订单号
     * @param userId 用户id
     * @param userType 用户类型
     * @param comments 评价数组
     * @param tag 租户
     * @param date 时间
     */
    private void insertOrderEvaluation(String orderNo, Long userId, Long driverId, Integer userType, List<Long> comments, String tag, Date date){
        // 查评论分值
        List<OaSysComment> oaSysComments = oaSysCommentMapper.selectList(
                Wrappers.<OaSysComment>lambdaQuery()
                        .eq(OaSysComment::getUserType, userType)
                        .eq(OaSysComment::getTag, tag)
                        .in(OaSysComment::getCommentId, comments)
        );
        String evaluationScore = "0";
        if (CheckUtil.objIsNotEmpty(oaSysComments)){
            OaSysComment oaSysComment = oaSysComments.get(0);
            if (ECommentGradeType.add.getValue().equals(oaSysComment.getCommentGradeType())){
                String commentGrade = oaSysComment.getCommentGrade();
                evaluationScore = String.format("+%s", commentGrade);
            } else {
                String commentGrade = oaSysComment.getCommentGrade();
                evaluationScore = String.format("-%s", commentGrade);
            }
        }
        OaOrderEvaluation oaOrderEvaluation = new OaOrderEvaluation();
        oaOrderEvaluation.setEvaluationId(IDUtil.nextId());
        oaOrderEvaluation.setOrderNo(orderNo);

        oaOrderEvaluation.setUserType(userType);
        oaOrderEvaluation.setEvaluationScore(evaluationScore);
        oaOrderEvaluation.setTagCommentContent(comments.toString().replace("[","").replace("]",""));
        oaOrderEvaluation.setIsShow(EEvaluationIsShow.yes.getValue());
        oaOrderEvaluation.setTag(tag);
        oaOrderEvaluation.setCreateTime(date);
        oaOrderEvaluation.setUserId(userId);
        oaOrderEvaluation.setCreateUser(userId);
        oaOrderEvaluation.setUpdateUser(userId);
        oaOrderEvaluation.setUpdateTime(date);
        int i = oaOrderEvaluationMapper.insert(oaOrderEvaluation);
        if (i != 1){
            throw PangException.create(EErrorCode.evaluationFailure);
        }
        this.updateWorkStatistics(userId, driverId, tag, userType, Integer.valueOf(evaluationScore), date);
    }

    /**
     * 更新服务分
     * @param userId 用户id
     * @param tag 租户
     * @param userType 用户类型
     * @param evaluationScore 计算分
     * @param date 当前时间
     */
    private void updateWorkStatistics(Long userId, Long driverId,  String tag, Integer userType, Integer evaluationScore, Date date){
        // 乘客评价 更新当日司机总服务分
        if (EClientUserType.c.getValue().equals(userType)){
            OaDUserInfo oaDUserInfo = oaDUserInfoMapper.selectOne(Wrappers.<OaDUserInfo>lambdaQuery().eq(OaDUserInfo::getTag, tag).eq(OaDUserInfo::getDriverId, driverId));
            if (CheckUtil.objIsEmpty(oaDUserInfo)){
                throw PangException.create(EErrorCode.unDUserInfo);
            }
            // 评分如果为空则赋值默认
            if (CheckUtil.objIsEmpty(evaluationScore)){
                evaluationScore = 0;
            }
            Integer totalServiceScore = oaDUserInfo.getTotalServiceScore();
            if (CheckUtil.objIsEmpty(totalServiceScore)){
                totalServiceScore = EServiceFraction.serviceFraction.getValue();
            }
            /*// 从redis中取司机日统计
            String workStatisticsRedisKey = String.format("%s%s", RedisPrefixConstant.WORK_OA_D_WORK_STATISTICS, driverId);
            String workStatisticsJsonStr = redisCommon.getStr(workStatisticsRedisKey);
            // redis有数据
            OaDWorkStatistics oaDWorkStatistics;
            if (CheckUtil.objIsNotEmpty(workStatisticsJsonStr)){
                oaDWorkStatistics = JSON.parseObject(workStatisticsJsonStr, OaDWorkStatistics.class);
                Integer totalServiceScore = oaDWorkStatistics.getTotalServiceScore();
                // 总分不为空累加
                if (CheckUtil.objIsNotEmpty(totalServiceScore)){
                    int totalScore = totalServiceScore + Integer.valueOf(evaluationScore);
                    if (totalScore > INIT_TOTAL_SERVICE_SCORE){
                        oaDWorkStatistics.setTotalServiceScore(INIT_TOTAL_SERVICE_SCORE);
                    } else {
                        oaDWorkStatistics.setTotalServiceScore(totalScore);
                    }
                }
                // 总分为空直接赋值默认值
                else {
                    int totalScore = INIT_TOTAL_SERVICE_SCORE + Integer.valueOf(evaluationScore);
                    if (totalScore > INIT_TOTAL_SERVICE_SCORE){
                        oaDWorkStatistics.setTotalServiceScore(INIT_TOTAL_SERVICE_SCORE);
                    } else {
                        oaDWorkStatistics.setTotalServiceScore(totalScore);
                    }
                }
                oaDWorkStatistics.setUpdateUser(userId);
                oaDWorkStatistics.setUpdateTime(date);
                redisCommon.set(workStatisticsRedisKey, JSON.toJSONString(oaDWorkStatistics));
            }
            // redis没数据去数据库找
            else {
                // 司机日统计
                List<OaDWorkStatistics> oaDWorkStatisticsS = oaDWorkStatisticsMapper.selectList(
                        Wrappers.<OaDWorkStatistics>lambdaQuery()
                                .eq(OaDWorkStatistics::getDriverId, driverId)
                                .eq(OaDWorkStatistics::getTag, tag)
                                .orderByDesc(OaDWorkStatistics::getCreateTime)
                );
                // 查询当天的工作统计
                if (CheckUtil.objIsNotEmpty(oaDWorkStatisticsS)){
                    oaDWorkStatistics = oaDWorkStatisticsS.get(0);
                    oaDWorkStatistics.setUpdateUser(userId);
                    oaDWorkStatistics.setUpdateTime(date);
                    int totalScore = oaDWorkStatistics.getTotalServiceScore() + evaluationScore;
                    if (totalScore > INIT_TOTAL_SERVICE_SCORE){
                        oaDWorkStatistics.setTotalServiceScore(INIT_TOTAL_SERVICE_SCORE);
                    } else {
                        oaDWorkStatistics.setTotalServiceScore(totalScore);
                    }
                    oaDWorkStatisticsMapper.updateById(oaDWorkStatistics);
                } else {
                    throw PangException.create(EErrorCode.pleaseCommut);
                }
            }*/
            oaDUserInfo.setUpdateTime(date);
            oaDUserInfo.setUpdateUser(userId);
            int totalScore = totalServiceScore + evaluationScore;
            if (totalScore > INIT_TOTAL_SERVICE_SCORE){
                oaDUserInfo.setTotalServiceScore(INIT_TOTAL_SERVICE_SCORE);
            } else {
                oaDUserInfo.setTotalServiceScore(totalScore);
            }
            oaDUserInfoMapper.updateById(oaDUserInfo);
        }
    }

    /**
     * 封装自费叫车
     * @param oaCOrderPersonal 自费叫车实体
     * @param userId 用户id
     * @param date 时间
     * @return
     */
    private String getZFJC(OaCOrderPersonal oaCOrderPersonal, Long userId, Integer userType, Date date){
        if (EClientUserType.c.getValue().equals(userType)){
            oaCOrderPersonal.setIsComment(EOrderIsComment.yes.getValue());
            oaCOrderPersonal.setUpdateTime(date);
            oaCOrderPersonal.setUpdateUser(userId+"");
            int i = oaCOrderPersonalMapper.updateById(oaCOrderPersonal);
            if (i != 1){
                throw PangException.create(EErrorCode.updateOrderFailure);
            }
        } else {
            this.commentOaDOrder(userId, date, oaCOrderPersonal.getPersonalId());
        }

        return EErrorCode.evaluationSuccess.getDesc();
    }

    /**
     * 封装个人公务
     * @param oaCOrderPersonalOfficial 个人公务实体
     * @param userId 用户id
     * @param date 时间
     * @return
     */
    private String getGRGW(OaCOrderPersonalOfficial oaCOrderPersonalOfficial, Long userId, Integer userType, Date date){
        if (EClientUserType.c.getValue().equals(userType)){
            oaCOrderPersonalOfficial.setIsComment(EOrderIsComment.yes.getValue());
            oaCOrderPersonalOfficial.setUpdateUser(userId+"");
            oaCOrderPersonalOfficial.setUpdateTime(date);
            int i = oaCOrderPersonalOfficialMapper.updateById(oaCOrderPersonalOfficial);
            if (i != 1){
                throw PangException.create(EErrorCode.updateOrderFailure);
            }
        } else {
            this.commentOaDOrder(userId, date, oaCOrderPersonalOfficial.getPersonalOfficialId());
        }
        return EErrorCode.evaluationSuccess.getDesc();

    }

    /**
     * 封装部门公务
     * @param oaCOrderDeptOfficial 部门公务实体
     * @param userId 用户id
     * @param date 时间
     * @return
     */
    private String getBMGW(OaCOrderDeptOfficial oaCOrderDeptOfficial, Long userId, Integer userType, Date date){
        if (EClientUserType.c.getValue().equals(userType)){
            oaCOrderDeptOfficial.setUpdateUser(userId+"");
            oaCOrderDeptOfficial.setUpdateTime(date);
            oaCOrderDeptOfficial.setIsComment(EOrderIsComment.yes.getValue());
            int i = oaCOrderDeptOfficialMapper.updateById(oaCOrderDeptOfficial);
            if (i != 1){
                throw PangException.create(EErrorCode.updateOrderFailure);
            }
        } else {
            this.commentOaDOrder(userId, date, oaCOrderDeptOfficial.getDeptOfficialId());
        }
        return EErrorCode.evaluationSuccess.getDesc();
    }

    /**
     * 封装审批公务
     * @param oaCOrderApprovalOfficial 审批公务
     * @param userId 用户id
     * @param date 时间
     * @return
     */
    private String getSPGW(OaCOrderApprovalOfficial oaCOrderApprovalOfficial, Long userId, Integer userType, Date date){
        if (EClientUserType.c.getValue().equals(userType)){
            oaCOrderApprovalOfficial.setUpdateTime(date);
            oaCOrderApprovalOfficial.setUpdateUser(userId);
            oaCOrderApprovalOfficial.setIsComment(EOrderIsComment.yes.getValue());
            int i = oaCOrderApprovalOfficialMapper.updateById(oaCOrderApprovalOfficial);
            if (i != 1){
                throw PangException.create(EErrorCode.updateOrderFailure);
            }
        } else {
            this.commentOaDOrder(userId, date, oaCOrderApprovalOfficial.getApprovalOfficialId());
        }
        return EErrorCode.evaluationSuccess.getDesc();
    }

    /**
     * 查询条件
     * @param userId 用户id
     * @param userType 用户类型
     * @param tag 租户
     * @param orderNo 订单号
     * @return
     */
    private QueryWrapper getQw(Long userId, Integer userType, String tag, String orderNo){
        QueryWrapper qw = new QueryWrapper();
        qw.eq("tag", tag);
        qw.eq("order_no", orderNo);
        if (EClientUserType.c.getValue().equals(userType)){
            qw.eq("user_id", userId);
        } else if (EClientUserType.d.getValue().equals(userType)){
            qw.eq("driver_id", userId);
        }
        return qw;
    }

    /**
     * 更新司机订单评价
     * @param userId 司机id
     * @param date 当前时间
     * @param userOrderId 订单id
     */
    private void commentOaDOrder(Long userId, Date date, Long userOrderId){
        OaDOrder oaDOrder = new OaDOrder();
        oaDOrder.setUpdateTime(date);
        oaDOrder.setIsComment(EOrderIsComment.yes.getValue());
        oaDOrder.setUpdateUser(userId);
        int update = oaDOrderMapper.update(oaDOrder, Wrappers.<OaDOrder>lambdaQuery().eq(OaDOrder::getUserOrderId, userOrderId));
        if (update != 1){
            throw PangException.create(EErrorCode.updateOrderFailure);
        }
    }

    /**
     * 判断司机订单是否评价过
     * @param orderNo 订单id
     * @return
     */
    private boolean isOaDOrderComment(String orderNo){
        OaDOrder oaDOrder = oaDOrderMapper.selectOne(Wrappers.<OaDOrder>lambdaQuery().eq(OaDOrder::getOrderNo, orderNo));
        if (EOrderIsComment.yes.equals(oaDOrder.getIsComment())){
            return true;
        } else {
            return false;
        }
    }
}
